package com.tcc.util.file;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.image.RenderedImage;
import java.io.*;
import java.util.List;

/**
 * PDF 工具类
 */
public class PDFUtilsByInterface {
    private static Font DEFAULT_FONT;

    static {
        try {
            DEFAULT_FONT = new Font(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static <T> boolean table2PDF(String file, String title, List<String> headers, List<T> data,
                                        TableWrite<T> write, String imgPath, Font font) {
        System.out.println("pdf 生成中……");
        /*
         * 1.新建document对象，可通过一下三种任意一种
         * 2.建立一个书写器(Writer)与document对象关联，通过书写器(Writer)可以将文档写入到磁盘中。 3.打开文档
         * 4.向文档中添加内容 5.关闭文档
         */
        try {
            Document document = new Document(PageSize.A4);
            PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
            // 判断字体 设置默认字体
            if (font == null) {
                font = DEFAULT_FONT;
            }

            if (title != null) {
                writeTitle(document, title, font);
            }
            // 写表格
            document.add(write.execute(headers, data, font));


            // 添加图片
            if (imgPath != null) {
                writeImg(imgPath, document);
            }

            document.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("pdf 生成失败");
            return false;
        }
        System.out.println("pdf 生成完毕");
        return true;
    }

    /**
     * PDF 转图片
     *
     * @param pdfFile // D://test//1.pdf
     * @param pngPath // D://test//xx.png
     * @return
     */
    public static boolean PDF2png(String pdfFile, String pngPath) {
        /*
         * 加载PDF文件 获取PDF页数 获取PDF渲染器 按页转换图片
         */
        try {
            PDDocument document = PDDocument.load(new File(pdfFile));
            int pages = document.getNumberOfPages();
            PDFRenderer renderer = new PDFRenderer(document);
            System.out.println("转图片ing……");
            for (int i = 0; i < pages; i++) {
                RenderedImage im = renderer.renderImage(i, 10);
                // ImageIO.write(im , "png", new File(pngPath+i+".png"));
                ImageIO.write(im, "png", new File(pngPath));
                System.out.println("转第" + (i + 1) + "页");
            }
            System.out.println("转成功");

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("转失败");
            return false;
        }
        return true;
    }

    /**
     * 获取字体
     *
     * @param winPath   win下字体路径 D://test//simkai.ttf
     * @param linuxPath linux 下字体路径 /tmp/simkai.ttf
     * @return
     */
    public static Font getFont(String winPath, String linuxPath) {
        String fontPath = System.getProperty("os.name").toLowerCase().contains("windows") ? winPath : linuxPath;

        try {
            return new Font(BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED));
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("获取失败");
            return DEFAULT_FONT;
        }
    }

    /**
     * 添加图片
     *
     * @param imgPath  图片路径
     * @param document
     * @throws IOException
     * @throws DocumentException
     */
    private static void writeImg(String imgPath, Document document) throws IOException, DocumentException {
        Image image = Image.getInstance(imgPath);
        image.setAlignment(Image.ALIGN_CENTER);
        image.scalePercent(40);// 依照比例缩放
        document.add(image);
    }

    /**
     * 写入文件标题
     *
     * @param document
     * @param title    标题
     * @param font     字体
     * @throws DocumentException
     */
    private static void writeTitle(Document document, String title, Font font) throws DocumentException {
        // 添加段落
        Paragraph paragraph = new Paragraph(title, font);
        paragraph.setAlignment(1); // 设置文字居中 0靠左 1，居中 2，靠右
        paragraph.setIndentationLeft(12); // 设置左缩进
        paragraph.setIndentationRight(12); // 设置右缩进
        paragraph.setFirstLineIndent(24); // 设置首行缩进
        paragraph.setLeading(20f); // 行间距
        paragraph.setSpacingBefore(5f); // 设置段落上空白
        paragraph.setSpacingAfter(10f); // 设置段落下空白
        document.add(paragraph);
    }

    /**
     * 添加水印
     *
     * @param is       输入流
     * @param os       输出流
     * @param mainMark
     * @param rootMark
     * @throws DocumentException
     * @throws IOException
     */
    public static void markTxt(InputStream is, OutputStream os, String mainMark, String rootMark)
            throws DocumentException, IOException {
        markTxt(0.5f, 60, true, is, os, mainMark, rootMark);
    }

    /**
     * 加图片水印
     *
     * @param iconPath
     * @param is
     * @param os
     * @param rootMark
     * @throws DocumentException
     * @throws IOException
     */
    public static void markImage(String iconPath, InputStream is, OutputStream os, String rootMark)
            throws DocumentException, IOException {
        markImage(iconPath, 0.5f, 60, false, is, os, rootMark);
    }

    /**
     * @param alpha    透明度 0-1
     * @param degree   角度 0-360
     * @param isUnder  水印置于文本上/下
     * @param is       输入IO
     * @param os       输出IO
     * @param mainMark 主文本
     * @param rootMark 页脚文本
     */
    private static void markTxt(float alpha, int degree, boolean isUnder, InputStream is, OutputStream os,
                                String mainMark, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        PdfStamper stamper = new PdfStamper(reader, os);

        try {
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);

            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            PdfContentByte content;
            int total = reader.getNumberOfPages() + 1;
            for (int i = 1; i < total; i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }
                content.setGState(gs);
                content.beginText();
                content.setColorFill(BaseColor.BLUE);
                content.setFontAndSize(base, 50);
                content.setTextMatrix(70, 200);
                content.showTextAligned(Element.ALIGN_CENTER, mainMark, 300, 350, degree);

                content.setColorFill(BaseColor.GREEN);
                content.setFontAndSize(base, 18);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();

            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }

    /**
     * @param iconPath 图标
     * @param alpha    透明度
     * @param degree   角度
     * @param isUnder  在内容下/上方加水印
     * @param is       输入IO
     * @param os       输出IO
     * @param rootMark 页脚文本描述
     */

    private static void markImage(String iconPath, float alpha, int degree, boolean isUnder, InputStream is,
                                  OutputStream os, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        // 关联源文件和目标文件
        PdfStamper stamper = new PdfStamper(reader, os);
        try {
            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);

            PdfContentByte content;
            // 获取页数 遍历 加水印
            for (int i = 1; i <= reader.getNumberOfPages(); i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }

                content.setGState(gs);
                content.beginText();

                Image image = Image.getInstance(iconPath);
                image.setAlignment(Image.LEFT | Image.TEXTWRAP);
                image.setRotationDegrees(degree);
                image.setAbsolutePosition(200, 200);
                image.scaleToFit(200, 200);

                content.addImage(image);
                content.setColorFill(BaseColor.BLACK);
                content.setFontAndSize(base, 8);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();
            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }

    // 内部类
    public interface TableWrite<T> {
        PdfPTable execute(List<String> headers, List<T> data, Font font);
    }
}
